package com.faya.green.utils;

import com.faya.green.abnormal.ServiceException;
import com.faya.green.model.User;
import net.coobird.thumbnailator.Thumbnails;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 用户 ：LX
 * 创建时间： 2018/7/11. 17:21
 * 地点：广州
 * 目的: 图片工具类
 * 结果：
 */
public class ImgUtils {

    private static Logger log = LoggerFactory.getLogger(ImgUtils.class);

    /**
     * 创建一个新的图片的名字
     * @return
     */
    public static String newImgName(){
        String date = DateUtils.getDate();
        String uuid = UUID.randomUUID().toString();
        return date + "_" + uuid;
    }

    /**
     * 头像处理（GIF和PNG放大是会变色.. 这个BUG一直没修复）
     *
     * of() 原图的string 文件地址或 file 或者 流
     * scale(1f) scale是可以指定图片的大小，值在0到1之间，1f就是原图大小，0.5就是原图的一半大小，这里的大小是指图片的长宽，默认是按照比例缩放的
     * size(width,height) 缩放大小
     * rotate(90).  顺时针旋转90度 正数：顺时针 负数：逆时针
     * outputQuality(0.8). // 图片压缩80%质量  不能和size()一起使用,值也是在0到1，越接近于1质量越好，越接近于0质量越差
     * toFile(文件要上传的位置)
     * watermark(位置，水印图，透明度) watermark(Positions.CENTER, ImageIO.read(new File("images/watermark.png")), 0.5f)
     * outputFormat("图像格式")   转化图像格式
     * toOutputStream 输出到 OutputStream
     * sourceRegion(0,0,200,200) 根据坐标裁剪
     * keepAspectRatio  默认是按照比例缩放的,值为false 时不按比例缩放
     *
     * 常用：
     *  	1 //不按比例，就按指定的大小进行缩放
     * 		 Thumbnails.of(fromPic).size(100, 100).keepAspectRatio(false).toFile(toPic);
     * 		2 	//旋转图片，rotate(角度),正数则为顺时针，负数则为逆时针
     * 	    	Thumbnails.of(fromPic).size(200,200).rotate(90).toFile(toPic);
     * 	    3   //图片尺寸不变，压缩图片文件大小outputQuality实现,参数1为最高质量
     * 	        Thumbnails.of(fromPic).scale(1f).outputQuality(0.25f).toFile(toPic);
     *
     * @param file springMVC的文件流
     * @param user 用户
     *      输出的图片的路径，比如 D://cc//1.jpg 如果直接写成 D://a/c  那么会在C下面创建c.jpg文件
     * @throws IOException
     */
    public static void headHandle (MultipartFile file, User user) throws IOException {
        if (file == null){
            throw new ServiceException("文件不存在，不能处理图片");
        }
        //获得图片文件名包括后缀
        String imgName = file.getOriginalFilename();
        //获取后缀（总后开始找.获得下标）
        String prefix = imgName.substring(imgName.lastIndexOf(".") + 1);
        //转换为小写
        prefix = prefix.toLowerCase();
        if (!checkImgSuffix(file)){
            throw new ServiceException("图片格式有误");
        }

        String imgHredSize = PropertiesUtil.getConfigValue("imgHredSize");
        if (file.getSize() > Integer.valueOf(imgHredSize)){
            throw new ServiceException("上传图片超过大小限制，请重新上传");
        }

        //新的图片名字 + 后缀
        String newImgName = newImgName();
        String name = newImgName + "." + prefix;
        //组合成路径
        String imgHred = PropertiesUtil.getConfigValue("imgHred");
        FileUtils.init(imgHred);

        //图片处理
        imgZip(prefix, file, imgHred, name, 75, 75);

        user.setImgHred(name);
    }

    /**
     * 对图片进行压缩处理
     * @param prefix 图片的后缀
     * @param file 文件
     * @param imgHred 要上传到的路径
     * @param name 图片的名字
     * @param width 压缩后图片的宽
     * @param height 压缩后图片的高
     */
    public static void imgZip(String prefix, MultipartFile file, String imgHred, String name, int width, int height) throws IOException {
        //对gif图进行区别处理， Thumbnails 存在bug，压缩剪切后的gif不会动了， GIF和PNG放大是会变色
        if ("gif".equals(prefix)){
            /**
             * 小于1024的图片可以使用  MultipartFile 来直接上传到服务器指定位置
             * MultipartFile 一些参数：
             *      getSize()方法获得文件长度
             *      isEmpty()方法判断上传文件是否为空文件 是返回true，其实调用的是还是getSize()
             *      getInputStream()方法将文件读取为java.io.InputStream流对象
             *      getContentType()方法获得文件类型
             *      transferTo（dest）方法将上传文件写到服务器上指定的文件
             */
            if (!file.isEmpty() && file.getSize() < 1024){
                file.transferTo(new File(imgHred + name));
            } else {
                FileUtils.multipartFileWriteFile(imgHred + name, file);
            }
        } else {
            //图片处理  理想的图片参数 121 75
            Thumbnails.of(file.getInputStream()).size(width, height).outputFormat(prefix).toFile(imgHred + name);
        }
    }


    /**
     * 创建一个新的文件名并添加到好后缀
     * @param file 图片文件
     * @return 一个新的文件名 + 后缀
     */
    public static String createImgNameConcat(MultipartFile file){
        //创建一个新的图片名给图片添加后缀
        String imgName = newImgName();
        //将后缀加在这后面
        if ("image/jpeg".equals(file.getContentType())){
            imgName = imgName.concat(".jpg");
        }else if ("image/png".equals(file.getContentType())){
            imgName = imgName.concat(".png");
        } else if ("image/bmp".equals(file.getContentType())){
            imgName = imgName.concat(".bmp");
        } else if ("image/gif".equals(file.getContentType())) {
            imgName = imgName.concat(".gif");
        } else {
            imgName = imgName.concat(".jpg");
        }
        return imgName;
    }

    /**
     * 检查图片的后缀是否正确
     * @param file 图片文件
     * @return  false 图片有误  true 图片格式正确
     */
    public static boolean checkImgSuffix(MultipartFile file){
        //获取图片文件名包括后缀
        String imgFileName = file.getOriginalFilename();
        //获取后缀（总后开始找.获得下标）
        String prefix = imgFileName.substring(imgFileName.lastIndexOf(".") + 1);
        //转换为小写
        prefix = prefix.toLowerCase();
        if (!("bmp".equals(prefix) || "png".equals(prefix) || "gif".equals(prefix) || "jpg".equals(prefix) || "jpeg".equals(prefix))){
            //图片格式有误，请重新上传
            return false;
        }
        return true;
    }

    /**
     * 读取存储在硬盘中的头像文件
     * @param id  图片的id （即保存的图片的名字）
     * @param response 需要一个response
     * @param key Properties文件的key
     * @param userParm 附加参数，当有的时候，则路径是从配置文件取出的路径 + 附加参数 + 图片名
     */
    public static void readImg(String id, HttpServletResponse response, String key, String userParm){

        if (CommonUtils.checkNull(id)){
            log.error("图片参数错误，不能读取图片...............");
            return;
        }

        if (CommonUtils.checkNull(key)){
            log.error("图片参数错误，不能读取图片...............");
            return;
        }

        //获取配置中的路径  imgHred 是配置文件中的key
        String imgPath = PropertiesUtil.getPath(key, PathUtil.getConfigPath());

        String path = null;
        if (!CommonUtils.checkNull(userParm)){
            path = imgPath + userParm + "\\" + id;

        } else {
            path = imgPath + id;
        }


        //判断文件是否存在
        if (!(FileUtils.fileIsExists(new File(path)))){
            log.error("图片不存在..............." + id);
            return;
        }

        imgOut(response, path);
    }

    /**
     * 直接流输出图片
     * @param response
     * @param imgPath 图片路径
     */
    public static void imgOut(HttpServletResponse response, String imgPath){
        FileInputStream fileInputStream = null;
        OutputStream out = null;
        try {
            fileInputStream = new FileInputStream(imgPath);
            //获得文件大小
            int i = fileInputStream.available();
            byte data[] = new byte[i];
            //读取数据，通过文件输入流将数据都到byte中
            fileInputStream.read(data);
            //设置返回的文件类型
            response.setContentType("image/*");
            out = response.getOutputStream();
            out.write(data);
            //清空缓冲区
            out.flush();

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (out != null){
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fileInputStream != null){
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    /**
     * 根据url下载图片到本地
     * @param imgUrl 图片url地址
     * @return 图片名
     */
    public static String downImgLoad(String imgUrl){
        if (CommonUtils.checkNull(imgUrl)){
            throw new ServiceException("图片url为空");
        }

        URL url = null;

        try {
            url = new URL(imgUrl);
            DataInputStream dataInputStream = new DataInputStream(url.openStream());
            String imgDownTemp = PropertiesUtil.getConfigValue("imgDownTemp");
            FileUtils.init(imgDownTemp);
            String imgName = newImgName() + ".jpg";
            String imgNamePath = imgDownTemp + imgName;
            FileOutputStream fileOutputStream = new FileOutputStream(new File(imgNamePath));
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

            byte[] bytes = new byte[1024];
            int length;
            while ((length = dataInputStream.read(bytes)) > 0){
                byteArrayOutputStream.write(bytes, 0, length);
            }

            byte[] context = byteArrayOutputStream.toByteArray();
            fileOutputStream.write(context);
            dataInputStream.close();
            fileOutputStream.close();
            return imgName;

        } catch (MalformedURLException e) {
            e.printStackTrace();
            throw new ServiceException("图片链接请求异常");
        } catch (IOException e) {
            e.printStackTrace();
            throw new ServiceException("图片获取失败");
        }
    }

}
